package com.koron.standard.riskSources.excel;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.ListUtils;
import com.koron.common.core.business.datadict.utils.DataDictTool;
import com.koron.common.core.util.CodeTools;
import com.koron.standard.riskSources.bean.po.RiskItem;
import com.koron.standard.riskSources.bean.po.RiskSources;
import com.koron.standard.riskSources.service.RiskItemService;
import com.koron.standard.riskSources.service.RiskSourcesService;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author jzp
 * @since 2022/2/22
 */
@Slf4j
public class RiskSourcesListener extends AnalysisEventListener<Map<Integer, String>> {

    private static final int BATCH_COUNT = 100;
    private List<RiskSources> riskSourcesList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    private List<RiskItem> riskItemList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
    private Map<String, String> standardRiskLevel;

    /**
     * K：风险源数据，String.join("&", firstTypeName, secondTypeName, thirdTypeName, fourthTypeName);
     * V：那条数据的id
     */
    private Map<String, String> riskSourceIds = new HashMap<>();

    private RiskSourcesService riskSourcesService;
    private RiskItemService riskItemService;

    public RiskSourcesListener(RiskSourcesService riskSourcesService, RiskItemService riskItemService) {
        this.riskSourcesService = riskSourcesService;
        this.riskItemService = riskItemService;
        Map<String, String> dataDictByCode = DataDictTool.getDataDictByCode("standardManagement", "standard_risk_level");
        this.standardRiskLevel = dataDictByCode.entrySet().stream().collect(Collectors.toMap(Map.Entry::getValue, Map.Entry::getKey));
    }

    /**
     * 一级分类	二级分类	三级分类	四级分类	风险描述	风险等级	可能性	严重性	控制措施
     */
    @Override
    public void invoke(Map<Integer, String> map, AnalysisContext analysisContext) {
        // 保存风险源
        RiskSources riskSources = new RiskSources();
        riskSources.setFirstTypeName(map.get(0));
        riskSources.setSecondTypeName(map.get(1));
        riskSources.setThirdTypeName(map.get(2));
        riskSources.setFourthTypeName(map.get(3));
        String id = riskSourceIds.get(riskSources.getMergeName());
        // 有则忽略，没有则保存
        if (id == null) {
            id = CodeTools.getCode32();
            riskSources.setId(id);
            riskSourcesList.add(riskSources);
            riskSourceIds.put(riskSources.getMergeName(), id);
        }

        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (riskSourcesList.size() >= BATCH_COUNT) {
            saveSource();
            // 存储完成清理 list
            riskSourcesList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }

        RiskItem riskItem = new RiskItem();
        riskItem.setDesc(map.get(4));
        // 数据字典
        riskItem.setRiskLevel(standardRiskLevel.get(map.get(5)));
        riskItem.setPossible(Integer.valueOf(map.get(6)));
        riskItem.setSerious(Integer.valueOf(map.get(7)));
        riskItem.setMeasures(map.get(8));
        riskItem.setSourceId(id);
        riskItemList.add(riskItem);
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
        if (riskItemList.size() >= BATCH_COUNT) {
            saveItem();
            // 存储完成清理 list
            riskItemList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext analysisContext) {
        saveSource();
        saveItem();
    }

    private void saveSource() {
        log.info("{}条风险源，开始存储数据库！", riskSourcesList.size());
        riskSourcesService.saveBatch(riskSourcesList);
        log.info("存储数据库成功！");
    }

    private void saveItem() {
        log.info("{}条风险项，开始存储数据库！", riskItemList.size());
        riskItemService.saveBatch(riskItemList);
        log.info("存储数据库成功！");
    }
}
